
import Foundation
import CommonCrypto


class EcUtils {
    static func toPublicKey(osnID:String) ->Data?{
        let pubKey = osnID.dropFirst(4)
        guard let pKey = MMSBarEEWrap.mmsBarEEWrap_d(String(pubKey)) else {
            return nil
        }
        if pKey.count < 2 {
            return nil
        }
        if pKey.count > 40 {
            return pKey[2..<35]
        }
        return pKey[2...]
    }
    static func toPrivateKey(osnID:String) -> Data? {
        let priKey = String(osnID.dropFirst(3))
        return Data(base64Encoded: priKey)
    }
    
    static func sha256(data: Data) -> Data {
//        var hash = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH))
//        data.withUnsafeBytes { buffer in
//            _ = CC_SHA256(buffer.baseAddress, CC_LONG(data.count), &hash)
//        }
//        return Data(hash)
        return MMSBarEDWrap.mmsBarEDWrap_data(data)
    }
    static func osnHash(data:Data) -> String {
        let hash = EcUtils.sha256(data: data)
        return hash.base64EncodedString()
    }
    static func osnSign(priKey:String, data:Data) -> String? {
        guard let pKey = EcUtils.toPrivateKey(osnID: priKey) else {
            return nil
        }
        guard let sign = MMSBarCCWrap.mmsBarCCWrap_s(pKey, data: data) else {
            return nil
        }
        return sign.base64EncodedString()
    }
    
    static func osnSign(_ data:Data) -> String? {
        guard let pKey = EcUtils.toPrivateKey(osnID: gimService.mOsnKey) else {
            return nil
        }
        guard let sign = MMSBarCCWrap.mmsBarCCWrap_s(pKey, data: data) else {
            return nil
        }
        return sign.base64EncodedString()
    }
    
    static func osnVerify(osnID:String, data:Data, sign:String) -> Bool {
        guard let rawData = sign.data(using: .utf8), let signData = Data(base64Encoded: rawData) else {
            return false
        }
        guard let pKey = EcUtils.toPublicKey(osnID: osnID) else {
            return false
        }
        return MMSBarCCWrap.mmsBarCCWrap_v(pKey, data: data, tag: signData)
    }
    static func ecIESEncrypt(osnID:String, data:Data) -> Data? {
        guard let pKey = toPublicKey(osnID: osnID) else {
            return nil
        }
        return MMSBarEDWrap.mmsBarEDWrap_eLong(pKey, data: data)
    }
    static func ecIESDecrypt(priKey:String, data:Data) -> Data? {
        guard let pKey = toPrivateKey(osnID: priKey) else {
            return nil
        }
        return MMSBarEDWrap.mmsBarEDWrap_dLong(pKey, data: data)
    }
    static func createOsnID(type:String) -> Array<String>? {
        guard let priKey = MMSBarWrap.mmsBarWrap_k(),
              let pubKey = MMSBarWrap.mmsBarWrap_p(priKey) else {
            return nil
        }
        var addr = Data([1,0])
        var osnType = "OSNU"
        if type == "group" {
            addr[1] = 1
            osnType = "OSNG"
        } else if type == "service" {
            addr[1] = 2
            osnType = "OSNS"
        }
        addr.append(pubKey)
        let osnID = osnType+MMSBarEEWrap.mmsBarEEWrap_e(addr)
        let osnKey = "VK0"+priKey.base64EncodedString()
        return [osnID, osnKey]
    }
    static func ecEncrypt2(osnID:String, data:Data) -> String? {
        let encData = ecIESEncrypt(osnID: osnID, data: data)
        return encData?.base64EncodedString()
    }
    static func ecDecrypt2(priKey:String, data:String) -> Data? {
        guard let b64Data = Data(base64Encoded: data) else {
            return nil
        }
        return ecIESDecrypt(priKey: priKey, data: b64Data)
    }
    static func b58Encode(data:Data) -> String {
        return MMSBarEEWrap.mmsBarEEWrap_e(data)
    }
    static func b58Decode(data:String) -> Data {
        return MMSBarEEWrap.mmsBarEEWrap_d(data)
    }
    static func getRepemd160(data:Data) -> Data{
        return MMSBarEDWrap.mmsBarEDWrap_raw(data)
    }
    static func createOsnIdFromMnemonic(seed:Data, password:String) -> Array<String>? {
        let hash1 = sha256(data: seed)
        let hash2 = sha256(data: hash1)
        guard let priKey1 = MMSBarWrap.mmsBarWrap_x(hash1),
              let pubKey1 = MMSBarWrap.mmsBarWrap_p(priKey1),
              let priKey2 = MMSBarWrap.mmsBarWrap_x(hash2),
              let pubKey2 = MMSBarWrap.mmsBarWrap_p(priKey2) else {
            return nil
        }
        let aesKey = sha256(data: password.data(using: .utf8) ?? Data())
        
        var addr = Data([2,0])
        let osnType = "OSNU"

        // create ripemd160
        let repemd160 = getRepemd160(data: pubKey2)
        addr.append(pubKey1)
        addr.append(repemd160)

        let osnID = osnType+MMSBarEEWrap.mmsBarEEWrap_e(addr)
        let osnKey = "VK0"+priKey1.base64EncodedString()
        let osnKey2 = priKey2.base64EncodedString()
        return [osnID,osnKey,osnKey2]
    }
    static func genAddress(priKey:Data) -> String? {
        guard let pubKey = MMSBarWrap.mmsBarWrap_p(priKey) else {
            return nil
        }
        var addr = Data([1,0])
        let osnType = "OSNU"
        addr.append(pubKey)
        return osnType+MMSBarEEWrap.mmsBarEEWrap_e(addr)
    }

    static func genPrivateKeyStr(priKey:Data) -> String? {
        return "VK0"+priKey.base64EncodedString()
    }
    
    static func genShadowKeyPair(privateKey: String) -> [String]? {
        guard let decodedData = OsnUtils.b64Decode(privateKey) else {
            return nil // 如果解码失败，返回nil
        }
          
        let shadowKeyData = decodedData
          
        let shadowAddress = EcUtils.genAddress(priKey: shadowKeyData)
        let shadowPrivateKeyStr = EcUtils.genPrivateKeyStr(priKey: shadowKeyData)
          
        let arr = [shadowAddress, shadowPrivateKeyStr] as? [String]
        return arr
    }

}
